package cc.rengu.igas.route.core.realize;

import cc.rengu.igas.route.common.constant.SmartRouteParamConstant;
import cc.rengu.igas.route.common.dao.RuleCfgMapper;
import cc.rengu.igas.route.common.dao.impl.RuleCfgMapperImpl;
import cc.rengu.igas.route.common.entity.RuleCfg;
import cc.rengu.igas.route.common.enums.RouteRuleTypeEnum;
import cc.rengu.igas.route.common.enums.SmartRouteRspEnums;
import cc.rengu.igas.route.core.helper.RouterHelper;
import cc.rengu.igas.route.core.model.ProdInfoBean;
import cc.rengu.igas.route.core.model.RouterReq;
import cc.rengu.igas.route.core.realize.impl.MultiRatioRouterChoiceImpl;
import cc.rengu.igas.route.core.realize.impl.StaticRouterChoiceImpl;
import cc.rengu.igas.route.core.realize.impl.WeightCfgRouterChoiceImpl;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;

import java.util.List;

/**
 * 智能路由实现类
 *
 * @author xionglz
 * @version 1.0
 * @date 2020-03-13
 */
public class Router {
    private RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    public List<ProdInfoBean> choice(RouterReq routerReq) throws Exception {
        RuleCfgMapper ruleCfgMapper = new RuleCfgMapperImpl();
        RuleCfg ruleCfg = null;
        List<ProdInfoBean> listProdInfo;
        //根据机构号,渠道号,交易分组查询 智能路由规则配置优先从缓存中获取，若发生异常，或无数据则从数据库获取
        String key = SmartRouteParamConstant.ROUTE_CONF_RULE + ":" + routerReq.getInstId() + ":" + routerReq.getSrcSysId() + ":" + routerReq.getTransChanlId() + ":" + routerReq.getTxnGroup();
        try {
            ruleCfg = JSON.parseObject(RedisUtil.onceGet(key), RuleCfg.class);
        } catch (Exception e) {
            //redis查询失败，则查数据库
            rglog.error(StringUtil.ExceptionToString(e));
            rglog.debug("通过redis查询智能路由配置信息出错！");
        }
        //redis查询失败或者结果为空
        if (ruleCfg == null) {
            ruleCfg = ruleCfgMapper.getTxnRuleCfg(routerReq.getInstId(), routerReq.getSrcSysId(), routerReq.getTransChanlId(), routerReq.getTxnGroup());
            //如果数据库中也找不到，则报错
            if (ruleCfg == null) {
                rglog.error("机构<{}>渠道<{}>交易分组<{}>未配置路由规则", routerReq.getInstId(), routerReq.getTransChanlId(), routerReq.getTxnGroup());
                throw new BizException(SmartRouteRspEnums.ILL_SRC_CHANNEL_ERROR.getRespCode(),
                        SmartRouteRspEnums.ILL_SRC_CHANNEL_ERROR.getRespDesc());
            }
            //数据库查询到的数据需要校验状态，redis的数据加载时已经过滤了状态
            if (!RouterHelper.judgeCommonRecordStatus(ruleCfg.getRuleStatus(), ruleCfg.getAuditStatus())) {
                rglog.error("机构<{}>渠道<{}>交易分组<{}>路由规则配置无效,状态<{}>审计状态<{}>", routerReq.getInstId(),
                        routerReq.getTransChanlId(), ruleCfg.getRuleStatus(), ruleCfg.getAuditStatus(), routerReq.getTxnGroup());
                throw new BizException(SmartRouteRspEnums.ILL_SRC_CHANNEL_ERROR.getRespCode(),
                        SmartRouteRspEnums.ILL_SRC_CHANNEL_ERROR.getRespDesc());
            }
        }

        //根据路由规则配置表中的规则类型判断路由方式
        RouterChoice routerChoice = getInstance(ruleCfg.getRuleType());
        if (null == routerChoice) {
            rglog.error("不支持的路由类型{}", ruleCfg.getRuleType());
            throw new BizException(SmartRouteRspEnums.MSG_VALID_CHECK_ERROR.getRespCode(),
                    SmartRouteRspEnums.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        listProdInfo = routerChoice.routerChoice(ruleCfg, routerReq);
        return listProdInfo;
    }

    private RouterChoice getInstance(String routeType) {
        if (RouteRuleTypeEnum.STATIC.getCode().equals(routeType)) {
            return new StaticRouterChoiceImpl();
        } else if (RouteRuleTypeEnum.MULTI_RATE.getCode().equals(routeType)) {
            return new MultiRatioRouterChoiceImpl();
        } else if (RouteRuleTypeEnum.SMART.getCode().equals(routeType)) {
            return new WeightCfgRouterChoiceImpl();
        } else {
            return null;
        }
    }
}
